<?php
namespace App\Common\Cla\Rbac;

use App\Common as com;
use App\Common\Cla\Rbac\Role as nameRole;

class Role extends com\Cla\ClaBase {
	
	// ===============================
	//
	//
	// 下面为静态方法
	//
	//
	// ===============================

	public static function newOfId( int $roleId ):nameRole\OfId {
		return new nameRole\OfId( $roleId );
	}

	/**
	 * 检查 $roleIds 是否包含 $permissionIds 权限
	 * @param array $roleIds
	 * @param array $permissionIds
	 * @return bool [true]包含 [false]不包含
	 */
	public static function isExistPermissionIdsOfRoleIds( array $roleIds, array $permissionIds ):bool {
		foreach( $permissionIds as $permissionId ){
			$permissionRoleIds = self::getRoleIdsOfPermissionIds( [ $permissionId ] );
			$permissionRoleIdsIndex = com\Lib\Fun\Array_::buildIndexArrayOfKeyPath( $permissionRoleIds );
			$isMatch = false;
			foreach( $roleIds as $roleId ){
				if( isset( $permissionRoleIdsIndex[ $roleId ] ) ){
					$isMatch = true;
					break;
				}
			}
			//
			if( $isMatch === false ){
				return false;
			}
		}
		//
		return true;
	}

	/**
	 * 获取拥有permissionId权限的所有RoleIds
	 * @param int $permissionId
	 * @return array
	 */
	public static function getRoleIdsOfPermissionId( int $permissionId ):array {
		// @TODO :o 需要优化(引入缓存？)
		$permissionAllIds = array_merge( [ $permissionId ], com\Cla\Rbac\Permission::getPermissionAndAllUpId( $permissionId ) );
		$rbacRoleDataUnit = com\Model\RbacRole::dataUnit();
		$rbacRoleDataUnit->fieldAndReset( [ 'id', 'parent_id' ] );
		foreach( $permissionAllIds as $permissionAllId ){
			$rbacRoleDataUnit->newData_PermissionIds()->orWhereLikeOfContinuousId( $permissionAllId );
		}
		$roleIds = $rbacRoleDataUnit->goModelQuery()->pluck( 'id' )->toArray();
		// 读取其他父id权限
		if( ! empty( $roleIds ) ){
			$roleIds = array_merge( $roleIds, self::getTreeOfAllRoleUpIds( $roleIds ) );
		}
		//
		//
		return $roleIds;
	}

	/**
	 * 获取同时拥有permissionIds的所有RoleIds
	 * @param array $permissionIds
	 * @return array
	 */
	public static function getRoleIdsOfPermissionIds( array $permissionIds ):array {
		$samePermissionRoles = null;
		foreach( $permissionIds as $permissionId ){
			$currentPermissionRoles = self::getRoleIdsOfPermissionId( $permissionId );
			// 获取重复的RoleIds
			if( $samePermissionRoles === null ){
				$samePermissionRoles = $currentPermissionRoles;
			}else{
				$samePermissionRoles = array_intersect( $samePermissionRoles, $currentPermissionRoles );
			}
		}
		//
		return $samePermissionRoles ?? [];
	}

	/**
	 * 获取所有上级
	 * @param array $roleIds
	 * @return array 不包含本级
	 */
	public static function getTreeOfAllRoleUpIds( array $roleIds ) {
		// 不做死循环检查，务必在更新时做好检查
		$rbacRoleDataUnit = com\Model\RbacRole::dataUnit();
		$rbacRoleDataUnit->goWhereDy()->ids( $roleIds );
		$rbacRoleDataUnit->newData_ParentId()->whereNotEq( 0 );
		$parentIds = $rbacRoleDataUnit->goModelQuery()->pluck( 'parent_id' )->toArray();
		//
		if( ! empty( $parentIds ) ){
			$parentIds = array_merge( $parentIds, self::getTreeOfAllRoleUpIds( $parentIds ) );
		}
		//
		return $parentIds;
	}

	/**
	 * 获取所有下级
	 * @param array $roleIds
	 * @return array 不包含本级
	 */
	public static function getTreeOfAllRoleDownIds( array $roleIds ) {
		// 不做死循环检查，需要在更新时做好检查
		$rbacRoleDataUnit = com\Model\RbacRole::dataUnit();
		$rbacRoleDataUnit->newData_ParentId()->whereIn( $roleIds );
		$downRoleIds = $rbacRoleDataUnit->goModelQuery()->pluck( 'id' )->toArray();
		//
		if( ! empty( $downRoleIds ) ){
			$downRoleIds = array_merge( $downRoleIds, self::getTreeOfAllRoleDownIds( $downRoleIds ) );
		}
		//
		return array_unique( $downRoleIds );
	}

	/**
	 * 获取Roles拥有的所有PermissionIds
	 * @param array $roleIds
	 * @return int[] PermissionIds
	 */
	public static function getPermissionIdsOfRoles( array $roleIds ):array {
		$allRoleIds = array_merge( $roleIds, self::getTreeOfAllRoleDownIds( $roleIds ) );
		//
		$rbacRoleManager = com\Model\RbacRole::dataManager();
		$rbacRoleManager->newData_Id()->whereIn( $allRoleIds );
		return $rbacRoleManager->newData_PermissionIds()->pluckOfContinuousIds()->setTypeOfInteger()->toArray();
	}

}
